﻿using System;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;

using JoinBoxCurrency;
using static JoinBoxCurrency.FileTool;
using static JoinBoxCurrency.Intranet;

namespace Beifenqi
{
    public partial class IntranetBackupDevice : Form
    { 

#if 宏
        private const string _pcNameMostly = "A2"; //局域网访问名称
        private const string _proName = "饰施图";   //局域网访问的共享文件夹
#elif 锐
        private const string _pcNameMostly = "HZR";//局域网访问主机名称
        private const string _proName = "施工图";   //局域网访问的共享文件夹
#endif 
        public string SPath { get; set; }
        private bool on_off = false;//暂停修改checkedListBox1 
         
        /// <summary>
        /// 点击计数,用于重新初始化
        /// </summary>
        private static int CheckedListBox1Counter = 0;

      

        public IntranetBackupDevice()
        { 
            InitializeComponent();
            //TopMost = true;//置顶窗体
            FormBorderStyle = FormBorderStyle.FixedSingle;//设置边框为不可调节 
            StartPosition = FormStartPosition.CenterScreen;//在当前屏幕中央 

            checkedListBox1.HorizontalScrollbar = true;//显示垂直滚动条
            checkedListBox1.ScrollAlwaysVisible = true;//显示水平滚动条  
            checkedListBox1.CheckOnClick = true;//按一下就打钩

            try
            {
#if true
                var getIpOrSegment = new GetIpOrSegment();

                NetworkSegment = getIpOrSegment.NetworkSegment;
                textBox3.Text = getIpOrSegment.NetworkSegment;

                label6.Text = "默认主机:" + _pcNameMostly;
                button1.TabIndex = 0;


                //获取exe完整路径,若是网络驱动器,就转换,本地就原本              
                SPath = IntranetPath.GetUNCPath(Process.GetCurrentProcess().MainModule.FileName);

                //可以获得不带文件名的路径
                SPath = Path.GetDirectoryName(SPath);
                string fileName = StringTool.PathToFileNameProjectName(SPath, 1);//获取文件名

                string[] rs = Regex.Split(SPath, "CAD阶段");
                if (rs.Length <= 1)
                {
                    rs = Regex.Split(SPath, _proName); //切割 "饰施图"  获取项目名
                }
                if (rs.Length > 1)
                {
                    textBox2.Text = StringTool.PathToFileNameProjectName(rs[0], 2);//获取项目名
                    label7.Text = "警告:无";
                }
                else
                {
                    textBox2.Text = fileName;
                    label7.Text = string.Format("警告:当前备份器exe不在 {0} 内,将采用以上对话框信息备份.", _proName);
                }

                var beifennian = StringTool.GetFlie4Number(textBox2.Text);
                if (beifennian == "0")//年份确定 
                {
                    DateTime currentTime = DateTime.Now;
                    textBox4.Text = currentTime.Year.ToString();
                }
                else
                {
                    textBox4.Text = beifennian;
                }
                {
                    //执行死循环修改的
                    //创建线程 Invoke方法是同步的方法，所以执行过程是有先后顺序的，所以就不会出现那个异常了
                    Thread newThread = new Thread(new ThreadStart(RunAddPcIp))
                    {
                        //加上这句话，否则在关闭窗体时会出现如下错误：在创建窗口句柄之前，不能在控件上调用 Invoke 或 BeginInvoke。
                        IsBackground = true
                    };
                    newThread.Start();
                }
                {
                    ThreadPool.GetMaxThreads(out int max, out int maxIo);
                    ThreadPool.GetMinThreads(out int min, out int minIo);

                    int ipNumbers = ipNumber + 1;
                    if (max - ipNumbers > 0)
                    {
                        max = ipNumbers;
                    }
                    if (maxIo - ipNumbers > 0)
                    {
                        maxIo = ipNumbers;
                    }
                    if (min - ipNumbers < 0)
                    {
                        min = ipNumbers;
                    }
                    if (minIo - ipNumbers < 0)
                    {
                        minIo = ipNumbers;
                    }
                    //启动线程池 
                    bool maxbool = ThreadPool.SetMaxThreads(max, maxIo);
                    bool minbool = ThreadPool.SetMinThreads(min, minIo);
                    if (maxbool && minbool)
                    {
                        Button4_Click(null, null);//开始就执行遍历局域网
                        //label7.Text = string.Format("注明:线程数设置{0},{1},{2},{3}", max, maxIo, min, minIo);
                    }
                    else
                    {
                        label7.Text = "警告:线程数设置失败";
                    }  
                }
#endif
            }
            catch (Exception e)
            {
                label7.Text = e.Message;
                throw e;
            }
        }

        /// <summary>
        /// 点击备份
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button1_Click(object sender, EventArgs e)
        {
            string dPath = textBox1.Text;
            if (dPath != "")
            {
                if (Directory.Exists(dPath))//防止第二次点击备份
                {
                    label7.ForeColor = Color.Blue;
                    label7.Text = "警告:路径已经存在,请更换路径!(是否重复备份了?)";
                }
                else
                {
                    label7.Text = "警告:正在备份......";
                    //新建线程执行复制
                    _thdCopyFile = new Thread(new ThreadStart(RunCopyFile));
                    _thdCopyFile.Start();
                }
            }
            else
            {
                label7.ForeColor = System.Drawing.Color.Red;
                label7.Text = "警告:备份路径为空!";
            }
        }

        private static Thread _thdCopyFile; //创建一个线程
        /// <summary>
        /// 设置线程，运行copy文件
        /// </summary>
        public void RunCopyFile()
        {
            int max = 0;
            FileTool.GetAllFileLength(SPath, ref max);

            Invoke((EventHandler)delegate
            {
                progressBar1.Value = 0;     //进度条当前位置为0
                progressBar1.Minimum = 0;   //进度条的最小值为0 
                progressBar1.Maximum = max; //进度条的最大值

                //然后要做的是每次拷贝计算文件大小,控制进度条 
                bool flag = Copy(SPath, textBox1.Text, progressBar1);//复制文件 
                if (flag)
                {
                    label7.ForeColor = Color.MediumSeaGreen;
                    label7.Text = "警告:备份成功!";
                    button5.TabIndex = 0;//设置焦点到打开文件夹
                }
                else
                {
                    //实现回滚效果                
                    DelPath(textBox1.Text, progressBar1);

                    label7.ForeColor = System.Drawing.Color.Blue;
                    label7.Text = "警告:备份不成功,已执行回滚,请再尝试!";
                }
            });
            _thdCopyFile.Abort();  //关闭线程 
        }

        /// <summary>
        /// Esc键退出  
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue == 27) //Esc键
            {
                Close();
            }
        }

        /// <summary>
        /// 窗体将比其内的控件优先获得键盘事件的激活权
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>  
        private void Form1_Load(object sender, EventArgs e)
        {
            KeyPreview = true;
        }

        /// <summary>
        /// 开始ping 遍历局域网
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button4_Click(object sender, EventArgs e)
        {
            //如果用多线程调用的话,会出现多个pingEnt和qiyongEnt值,对加入表造成错误例如多个A2 
            try
            {
                //暂停加表,清空表,初始化
                on_off = false;
                {
                    pingEnt++;
                    qiyongEnt++;
                    NetworkSegment = textBox3.Text;

                    CheckedListBox1Counter = 0;
                    for (int i = 0; i < checkedListBox1.Items.Count; i++)
                    {
                        checkedListBox1.Items.Clear();
                    }
                    Initialization();
                }
                on_off = true; //继续加入表中 

                for (int i = 0; i < ipNumber; i++)//生成255个线程
                {
                    ThreadPool.QueueUserWorkItem(new WaitCallback(PingIP), new int[] { i, qiyongEnt });
                }
            }
            catch
            {
                label7.Text = "警告:RunPing出错";
            }
        }

        /// <summary> 
        /// 通过委托实现死循环修改面板
        /// </summary>
        ///  https://blog.csdn.net/htiannuo/article/details/52229695
        public void RunAddPcIp()
        {
            HostInformation[] conames = new HostInformation[] { };
            StringBuilder kongge;

            while (true)
            {
                if (on_off)
                {
                    lock (ComputerNames)
                    {
                        conames = ComputerNames.ToArray();
                    }
                    if (CheckedListBox1Counter < conames.Length)
                    {
                        var conameN = conames[CheckedListBox1Counter];
                        string hostName = conameN.HostName;
                        if (hostName != "" && conameN.HostIP != "")//锁了就应该不会出现这样的问题了  
                        {
                            hostName = hostName.ToUpper();
                            Invoke((EventHandler)delegate
                            {
                                //ip可能为名称,ip长度 255.255.255.255  15长+5个空格=20 
                                int bukongge = 20 - hostName.Length;
                                kongge = new StringBuilder();
                                for (int i = 0; i < bukongge; i++)
                                {
                                    kongge.Append(" ");
                                }
                                checkedListBox1.Items.Add(hostName + kongge + conameN.HostIP + " \t" + conameN.Remarks);

                                if (hostName == _pcNameMostly)
                                {
                                    //选择默认主机
                                    checkedListBox1.SetItemCheckState(CheckedListBox1Counter, CheckState.Checked);//打钩
                                    checkedListBox1.SelectedIndex = CheckedListBox1Counter;//焦点项  
                                }
                            });
                        }
                        CheckedListBox1Counter++;
                        //这个不能放在Invoke里面，不然又Form1窗体假死情况
                        Thread.Sleep(400);
                    }
                }
            }
        }

        /// <summary>
        /// 打开文件夹
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button5_Click(object sender, EventArgs e)
        {
            if (Directory.Exists(textBox1.Text)) //若路径存在
            {
                Process.Start("explorer.exe", textBox1.Text);
            }
            else
            {
                label7.ForeColor = System.Drawing.Color.Red;
                label7.Text = "警告:备份路径为空!请点击备份再点我~";
            }
        }

        /// <summary>
        /// 弄成单选
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CheckedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            if (e.CurrentValue == CheckState.Checked)
            {
                return;//取消选中就不用进行以下操作
            }
            for (int i = 0; i < ((CheckedListBox)sender).Items.Count; i++)
            {
                ((CheckedListBox)sender).SetItemChecked(i, false);//将所有选项设为不选中
            }
            e.NewValue = CheckState.Checked;//刷新  
        }

        private static string patha = "";
        private static string pathTime = "";

        /// <summary>
        /// CheckedListBox1选择事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void CheckedListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            //  if (buchufagenggai)用了的话会无法直接出现在 textBox1.Text
            {
                //获取唯一选中项,修改textBox1路径  
                for (int j = 0; j < checkedListBox1.Items.Count; j++)
                {
                    if (checkedListBox1.GetItemChecked(j))
                    {
                        try
                        {
                            var conames = ComputerNames.ToArray();
                            string time = StringTool.GetTimeNoSeconds(out int miao);
                            string pathb = @"\\" + conames[j].HostName + _SharedFolders;
                            string pathc = @"\\" + conames[j].HostIP + _SharedFolders;

                            for (int i = 0; true; i++)
                            {
                                bool pb = Directory.Exists(pathb);
                                if (!pb)
                                {
                                    pb = Directory.Exists(pathc);
                                    patha = pathc;
                                }
                                else
                                {
                                    patha = pathb;
                                }
                                if (pb) //存在一级
                                {
                                    pathTime = StringTool.GetTimeName(time, miao + i);//循环名称不加长 
                                    string path = ChangPath(textBox4.Text, textBox2.Text);
                                    if (!Directory.Exists(path)) //存在就循环
                                    {
                                        textBox1.Text = path;
                                        break;
                                    }
                                }
                                else
                                {
                                    DialogResult dr = MessageBox.Show(
                                        patha + Environment.NewLine + "\n无法连接,没有开机?不存在机名?没有访问权限?", "惊惊连盒", MessageBoxButtons.OK);
                                    break;
                                }
                            }
                        }
                        catch
                        { }
                        break;
                    }
                }
            }
        }

        //关闭
        private void Button2_Click(object sender, EventArgs e)
        {
            Close();
        }

        //作者信息
        private void Button3_Click(object sender, EventArgs e)
        {
            string jj = "www.cnblogs.com/JJBox";
            DialogResult dr = MessageBox.Show(
                "说明:本程序会在'备份器exe所在位置'进行备份" +
                 Environment.NewLine + "此文件夹前将视为'项目文件夹': " + _proName +
                 Environment.NewLine + "更换网段时候后需要重新ping" +
                 Environment.NewLine + "深圳壹席设计事务所有限公司&东莞市罗道夫空间设计有限公司" +
                 Environment.NewLine + "\n作者:刘启宏    企鹅:540762622" +
                 Environment.NewLine + "博客: " + jj + " ('确定' 进入博客)"
                , "惊惊连盒",
                MessageBoxButtons.OKCancel
                );
            if (dr == DialogResult.OK)
            {
                System.Diagnostics.Process.Start(jj);
            }
        }

        private void TextBox2_TextChanged(object sender, EventArgs e)
        {
            if (patha != "")//防止初始化的时候就更改
            {
                textBox1.Text = ChangPath(textBox4.Text, textBox2.Text);
            }
        }

        /// <summary>
        /// 备份全路径
        /// </summary>
        /// <param name="beifennian"></param>
        /// <param name="project"></param>
        /// <returns></returns>
        private string ChangPath(string beifennian, string project)
        {
            return patha + @"\" + beifennian + @"\" + project + @"\" + _proName + @"\" + pathTime;
        }

    }
}
